package cn.itsource.ymcc.service.impl;

import cn.itsource.util.AssertUtil;
import cn.itsource.ymcc.domain.KillActivity;
import cn.itsource.ymcc.domain.KillCourse;
import cn.itsource.ymcc.mapper.KillActivityMapper;
import cn.itsource.ymcc.service.IKillActivityService;
import cn.itsource.ymcc.service.IKillCourseService;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.redisson.api.RSemaphore;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author Cherish
 * @since 2022-08-23
 */
@Service
public class KillActivityServiceImpl extends ServiceImpl<KillActivityMapper, KillActivity> implements IKillActivityService {
    @Autowired
    private IKillCourseService killCourseService;
    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;
    @Autowired
    private RedissonClient redissonClient;

    /**
     * 活动发布
     * 判断：
     *  1.活动状态必须是待发布
     *  2.当前系统时间小于活动结束时间
     *  3.活动对应的秒杀课程存入redis
     *  4.将每个课程对应的库存 存成信号量
     */

    @Override
    public void publish(Long id) {
        // 查询到数据做处理
        KillActivity killActivity = selectById(id);

        AssertUtil.isNotNull(killActivity,"活动不存在！");
        // 检查活动状态，必须为未发布才行
        boolean isWait = killActivity.getPublishStatus() == KillActivity.STATES_WAIT_PUBLISH;
        AssertUtil.isTrue(isWait,"活动状态不合法！");
        // 当前系统时间必须要小于活动结束时间
        boolean isStart = new Date().before(killActivity.getEndTime());
        AssertUtil.isTrue(isStart,"活动时间不合法！");
        // 活动对应的秒杀课程存入redis,并修改发布状态


        Wrapper<KillCourse> query = new EntityWrapper<>();
        query.eq("activity_id",killActivity.getId());

        List<KillCourse> killCourses = killCourseService.selectList(query);
        killActivity.setPublishStatus(KillActivity.STATES_ONLINE);
        killActivity.setPublishTime(new Date());

        killCourses.stream().forEach(killCourse -> {
            //3.将每个课程对应的库存 存成信号量
            String semaphoreKey = killActivity.getId() + ":" + killCourse.getId();
            RSemaphore semaphore = redissonClient.getSemaphore(semaphoreKey);
            boolean success = semaphore.trySetPermits(killCourse.getKillCount());
            if(success){
                //4.使用hash结构，把秒杀课程存入redis中
                redisTemplate.opsForHash().put(
                        "activity:"+ killActivity.getId(),
                        killCourse.getId().toString(),
                        killCourse
                );
                killCourse.setPublishStatus(killActivity.getPublishStatus());
                killCourse.setPublishTime(killActivity.getPublishTime());
                killCourseService.updateById(killCourse);
            }else{
                //兜底，添加一条失败记录到数据库中
            }
        });
        updateById(killActivity);
    }
}
